package com.hodgepodge.sso.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.hodgepodge.api.mapper.RoleMapper;
import com.hodgepodge.api.mapper.UserMapper;
import com.hodgepodge.commons.entity.User;
import com.hodgepodge.commons.enums.ResultCodeEnum;
import com.hodgepodge.commons.exception.ApiException;
import com.hodgepodge.sso.entity.AuthUser;
import com.hodgepodge.sso.entity.JwtAuthUser;
import org.springframework.beans.BeanUtils;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;

import javax.annotation.Resource;

/**
 * title UserDetailsServiceImpl
 * projectName colorful-blog
 * desc 实现UserDetailsService，从数据库中加载用户信息 ==> 用户名、密码及角色名
 * <p>
 * Spring Security中进行身份验证的是AuthenticationManager接口，ProviderManager是它的一个默认实现，但它并不用来处理身份认证，
 * 而是委托给配置好的AuthenticationProvider，每个AuthenticationProvider会轮流检查身份认证。检查后或者返回Authentication对象或者抛出异常。
 * <p>
 * 验证身份就是加载响应的UserDetails，看看是否和用户输入的账号、密码、权限等信息匹配。
 * 此步骤由实现AuthenticationProvider的DaoAuthenticationProvider（它利用UserDetailsService验证用户名、密码和授权）处理。
 * 包含 GrantedAuthority 的 UserDetails对象在构建 Authentication对象时填入数据。
 *
 * @author jiangjian
 * @date 2021/7/2 15:53
 */
public class UserDetailsServiceImpl implements UserDetailsService {

    @Resource
    private UserMapper userMapper;

    @Resource
    private RoleMapper roleMapper;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq("username", username);
        User user = userMapper.selectOne(wrapper);

        if (user == null) {
            // 实际当用户不存在时，应该页面显示错误信息，并跳转到登录界面
            throw new ApiException(ResultCodeEnum.INVALID_USERNAME);
        }

        AuthUser authUser = new AuthUser();
        BeanUtils.copyProperties(user, authUser);

        authUser.setRoles(roleMapper.getRolesByUserId(user.getUserId()));

        return new JwtAuthUser(authUser);
    }
}
